package fr.castorflex.openharmony.smoothprogressbar;

import fr.castorflex.openharmony.smoothprogressbar.curvetype.AccelerateDecelerateCurveType;
import fr.castorflex.openharmony.smoothprogressbar.curvetype.AccelerateCurveType;
import fr.castorflex.openharmony.smoothprogressbar.curvetype.DecelerateCurveType;
import fr.castorflex.openharmony.smoothprogressbar.curvetype.LinearCurveType;
import fr.castorflex.openharmony.smoothprogressbar.curvetype.TimeCurveType;
import fr.castorflex.openharmony.smoothprogressbar.utils.ResUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.agp.render.Canvas;
import ohos.app.Context;

/**
 * Created by castorflex on 11/10/13.
 */
public class SmoothProgressBar extends Text implements Component.LayoutRefreshedListener, Component.DrawTask {

    private int color;

    private static final String spb_default_color = "spb_default_color";

    private int sectionsCount;

    private static final String spb_default_sections_count = "spb_default_sections_count";

    private int separatorLength;

    private static final String spb_default_stroke_separator_length = "spb_default_stroke_separator_length";

    private float strokeWidth;

    private static final String spb_default_stroke_width = "spb_default_stroke_width";

    private float speed;

    private static final String spb_default_speed = "spb_default_speed";

    private float speedProgressiveStart;

    private static final String spb_progressiveStart_speed = "spb_progressiveStart_speed";

    private float speedProgressiveStop;

    private static final String spb_progressiveStop_speed = "spb_progressiveStop_speed";

    private int icurvetype;

    private static final String spb_curvetype = "spb_curvetype";

    private boolean reversed;

    private static final String spb_default_reversed = "spb_default_reversed";

    private boolean mirrorMode;

    private static final String spb_default_mirror_mode = "spb_default_mirror_mode";

    private int colorsId;

    private static final String spb_colors = "spb_colors";

    private boolean progressiveStartActivated;

    private static final String spb_default_progressiveStart_activated = "spb_default_progressiveStart_activated";

    private Element backgroundDrawable;

    private static final String spb_background = "spb_background";

    private boolean generateBackgroundWithColors;

    private static final String spb_generate_background_with_colors = "spb_generate_background_with_colors";

    private boolean gradients;

    private static final String spb_gradients = "spb_gradients";

    private int[] colors = null;

    private static final int spb_curvetype_linear = 0;

    private static final int spb_curvetype_accelerate = 1;

    private static final int spb_curvetype_decelerate = 2;

    private static final int spb_curvetype_acceleratedecelerate = 3;

    private float formFact = 1.2f;

    private SmoothProgressDrawable.Builder builder;

    private SmoothProgressDrawable mSmoothProgressDrawable;

    private AttrSet mAttrSet;

    private Context mContext;

    public SmoothProgressBar(Context context, AttrSet attrs) {
        super(context, attrs);
        mContext = context;

        if (attrs != null) {
            mAttrSet = attrs;
            color = mAttrSet.getAttr(spb_default_color).isPresent() ? mAttrSet.getAttr(spb_default_color)
                .get()
                .getColorValue()
                .getValue() : 0x33b5e5;
            sectionsCount = mAttrSet.getAttr(spb_default_sections_count).isPresent() ? mAttrSet.getAttr(
                spb_default_sections_count).get().getIntegerValue() : 4;
            separatorLength = mAttrSet.getAttr(spb_default_stroke_separator_length).isPresent() ? mAttrSet.getAttr(
                spb_default_stroke_separator_length).get().getDimensionValue() : 4;
            strokeWidth = mAttrSet.getAttr(spb_default_stroke_width).isPresent() ? mAttrSet.getAttr(
                spb_default_stroke_width).get().getDimensionValue() : 4;
            speed = mAttrSet.getAttr(spb_default_speed).isPresent() ? mAttrSet.getAttr(spb_default_speed)
                .get()
                .getFloatValue() : Float.parseFloat("1");
            speedProgressiveStart = mAttrSet.getAttr(spb_progressiveStart_speed).isPresent() ? mAttrSet.getAttr(
                spb_progressiveStart_speed).get().getFloatValue() : speed;
            speedProgressiveStop = mAttrSet.getAttr(spb_progressiveStop_speed).isPresent() ? mAttrSet.getAttr(
                spb_progressiveStop_speed).get().getFloatValue() : speed;
            icurvetype = mAttrSet.getAttr(spb_curvetype).isPresent() ? mAttrSet.getAttr(spb_curvetype)
                .get()
                .getIntegerValue() : -1;
            reversed = mAttrSet.getAttr(spb_default_reversed).isPresent() ? mAttrSet.getAttr(spb_default_reversed)
                .get()
                .getBoolValue() : false;
            mirrorMode = mAttrSet.getAttr(spb_default_mirror_mode).isPresent() ? mAttrSet.getAttr(
                spb_default_mirror_mode).get().getBoolValue() : false;
            colorsId = mAttrSet.getAttr(spb_colors).isPresent()
                ? mAttrSet.getAttr(spb_colors).get().getIntegerValue()
                : 1;
            progressiveStartActivated = mAttrSet.getAttr(spb_default_progressiveStart_activated).isPresent()
                ? mAttrSet.getAttr(spb_default_progressiveStart_activated).get().getBoolValue()
                : false;
            backgroundDrawable = mAttrSet.getAttr(spb_background).isPresent() ? mAttrSet.getAttr(spb_background)
                .get()
                .getElement() : null;
            generateBackgroundWithColors = mAttrSet.getAttr(spb_generate_background_with_colors).isPresent()
                ? mAttrSet.getAttr(spb_generate_background_with_colors).get().getBoolValue()
                : false;
            gradients = mAttrSet.getAttr(spb_gradients).isPresent() ? mAttrSet.getAttr(spb_gradients)
                .get()
                .getBoolValue() : false;
        } else {
            color = 0x33b5e5;
            sectionsCount = 4;
            separatorLength = 4;
            strokeWidth = 4;
            speed = Float.parseFloat("1");
            speedProgressiveStart = speed;
            speedProgressiveStop = speed;
            icurvetype = -1;
            reversed = false;
            mirrorMode = false;
            colorsId = 0;
            progressiveStartActivated = false;
            backgroundDrawable = null;
            generateBackgroundWithColors = false;
            gradients = false;
        }

        TimeCurveType timeCurveType = new AccelerateCurveType(formFact);

        if (icurvetype == -1) {
            timeCurveType = new LinearCurveType();
        }
        if (icurvetype != -1) {
            switch (icurvetype) {
                case spb_curvetype_acceleratedecelerate:
                    timeCurveType = new AccelerateDecelerateCurveType();
                    break;
                case spb_curvetype_decelerate:
                    timeCurveType = new DecelerateCurveType(formFact);
                    break;
                case spb_curvetype_linear:
                    timeCurveType = new LinearCurveType();
                    break;
                case spb_curvetype_accelerate:
                default:
                    timeCurveType = new AccelerateCurveType(formFact);
            }
        }

        //colors
        if (colorsId != 0) {
            colors = new int[] {ResUtil.getColor(context, ResourceTable.Color_cpb_default_color)};
        }

        builder = new SmoothProgressDrawable.Builder(mContext).speed(speed)
            .progressiveStartSpeed(speedProgressiveStart)
            .progressiveStopSpeed(speedProgressiveStop)
            .curvetype(timeCurveType)
            .sectionsCount(sectionsCount)
            .separatorLength(separatorLength)
            .strokeWidth(strokeWidth)
            .reversed(reversed)
            .mirrorMode(mirrorMode)
            .progressiveStart(progressiveStartActivated)
            .gradients(gradients);

        if (backgroundDrawable != null) {
            builder.backgroundDrawable(backgroundDrawable);
        }

        if (generateBackgroundWithColors) {
            builder.generateBackgroundUsingColors();
        }

        if (colors != null && colors.length > 0) {
            builder.colors(colors);
        }

        setLayoutRefreshedListener(this::onRefreshed);
        addDrawTask(this::onDraw);
    }

    public void setColors(int[] colorsInput) {
        builder.colors(colorsInput);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        drawIndeterminateProgress(canvas);
    }

    boolean mIndeterminateProgressMode = true;

    @Override
    public void onRefreshed(Component component) {
        if (mIndeterminateProgressMode) {
            invalidate();
        }
    }

    private void drawIndeterminateProgress(Canvas canvas) {
        if (mSmoothProgressDrawable == null) {
            mSmoothProgressDrawable = builder.build();
            mSmoothProgressDrawable.setComponent(this);
            mSmoothProgressDrawable.start();
            mSmoothProgressDrawable.drawToCanvas(canvas);

        } else {
            mSmoothProgressDrawable.drawToCanvas(canvas);
        }

    }

    private SmoothProgressDrawable checkIndeterminateDrawable() {
        return mSmoothProgressDrawable;
    }

    public void setSmoothProgressDrawablecurvetype(TimeCurveType curvetype, float factor) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setcurvetype(curvetype, factor);
        } else {
            builder.curvetype(curvetype);
        }
    }

    public void setSmoothProgressDrawableColors(int[] colors) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setColors(colors);
        } else {
            builder.colors(colors);
        }
    }

    public void setSmoothProgressDrawableColor(int color) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setColor(color);
        }
    }

    public void setSmoothProgressDrawableSpeed(float speed) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setSpeed(speed);
        } else {
            builder.speed(speed);
        }
    }

    public void setSmoothProgressDrawableProgressiveStartSpeed(float speed) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setProgressiveStartSpeed(speed);
        } else {
            builder.progressiveStartSpeed(speed);
        }
    }

    public void setSmoothProgressDrawableProgressiveStopSpeed(float speed) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setProgressiveStopSpeed(speed);
        } else {
            builder.progressiveStopSpeed(speed);
        }
    }

    public void setSmoothProgressDrawableSectionsCount(int sectionsCount) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setSectionsCount(sectionsCount);
        } else {
            builder.sectionsCount(sectionsCount);
        }
    }

    public void setSmoothProgressDrawableSeparatorLength(int separatorLength) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setSeparatorLength(separatorLength);
        } else {
            builder.separatorLength(separatorLength);
        }

    }

    public void setSmoothProgressDrawableStrokeWidth(float strokeWidth) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setStrokeWidth(strokeWidth);
        } else {
            builder.strokeWidth(strokeWidth);
        }
    }

    public void setSmoothProgressDrawableReversed(boolean reversed) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setReversed(reversed);
        } else {
            builder.reversed(reversed);
        }
    }

    public void setSmoothProgressDrawableMirrorMode(boolean mirrorMode) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setMirrorMode(mirrorMode);
        } else {
            builder.mirrorMode(mirrorMode);
        }
    }

    public void setProgressiveStartActivated(boolean progressiveStartActivated) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setProgressiveStartActivated(progressiveStartActivated);
        } else {
            builder.gradients(progressiveStartActivated);
        }
    }

    public void setSmoothProgressDrawableCallbacks(SmoothProgressDrawable.Callbacks listener) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setCallbacks(listener);
        }
    }

    public void setSmoothProgressDrawableBackgroundDrawable(Element drawable) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setBackgroundDrawable(drawable);
        }
    }

    public void setSmoothProgressDrawableUseGradients(boolean useGradients) {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().setUseGradients(useGradients);
        } else {
            builder.gradients(useGradients);
        }
    }

    public void progressiveStart() {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().progressiveStart();
        }
    }

    public void progressiveStop() {
        if (checkIndeterminateDrawable() != null) {
            checkIndeterminateDrawable().progressiveStop();
        }
    }
}
